/*
 * By: Werner Schuster (murphee)
 * 
 * Copyright (c) 2005-2006 Werner Schuster (murphee)
 * 
 * This file is part of the EclipseShell project. EclipseShell is subject 
 * to the Eclipse Public License (EPL) available at
 * http://www.eclipse.org/org/documents/epl-v10.php
 * or in the file /epl-v10.html in the source for other info
 * see the /eclipseshell.license file
 */
package net.sf.eclipseshell.extensions;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.List;


import net.sf.eclipseshell.EclipseShellPlugin;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.ui.JavadocContentAccess;
import org.eclipse.jface.text.contentassist.CompletionProposal;

public class DefaultJavaEnvironment implements IJavaEnvironment {

	IProject project_;
	
	public DefaultJavaEnvironment(IProject proj) {
		project_ = proj;
	}
	
	
	/**
	 * Looks  up the 
	 * @param currMethod
	 * @return the JavaDoc OR NULL if none could be found
	 */
	public String getJavaDoc(IMethod currMethod) {
		String retValue = null;
		if(project_ != null){
			try {
//				IType clazz = getJdtType(currMethod.getDeclaringClass());
//				// get the arg types as String[]
//				Class[] argTypes = currMethod.getParameterTypes();
//				String[] argTypesAsString = new String[argTypes.length ];
//				for (int i = 0; i < argTypes.length; i++) {
//					Class class1 = argTypes[i];
//					argTypesAsString[i] = translateToJdt(class1);
//				}
//				// add return value
////				argTypesAsString[argTypesAsString.length-1] = translateToJdt(currMethod.getReturnType());
//				
////				IMethod[] jdtMethod = clazz.getMethods();
////				IMethod jdtCurrMethod = jdtMethod[0];
//				IMethod jdtCurrMethod = clazz.getMethod(currMethod.getName(), argTypesAsString);
				currMethod.getOpenable().open(null);
//				String sig = jdtCurrMethod.getSignature();
				
				Reader docContent = JavadocContentAccess.getContentReader(currMethod, true);
				if(docContent != null){
					retValue = readIntoString(docContent);
				}

			} catch (Exception e) {
				EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
			}
		}
		return retValue;
	}

	public String translateToJdt(Class returnType) {
		String name = returnType.getName();
		String retVal = name;
//		if("int".equals(name)){
//			retVal = "I";
//		} else if("long".equals(name)){
//			retVal = "J";
//		} else if("char".equals(name)){
//			retVal = "C";
//		} else if("byte".equals(name)){
//			retVal = "B";
//		} else if("float".equals(name)){
//			retVal = "F";
//		} else if("double".equals(name)){
//			retVal = "D";
//		} else if("short".equals(name)){
//			retVal = "S";
//		}  else if("boolean".equals(name)){
//			retVal = "S";
//		} else {
//			retVal = name;
//		}
		retVal = Signature.createTypeSignature(name.toCharArray(), false);
		
		return retVal;
	}

	/**
	 * Looks  up the  
	 * @param currclass
	 * @return the JavaDoc OR NULL if none could be found
	 */
	public String getJavaDoc(IType type) {
		String retValue = null;
		if(project_ != null){				
				try {
					type.getOpenable().open(null);
					
					Reader docContent = JavadocContentAccess.getContentReader(type, true);
					if(docContent != null){
						retValue = readIntoString(docContent);
					}
				} catch (Exception e) {
					EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
				}				
		}
		return retValue;
	}

	public IType getJdtType(Class currClass) {
		return getJdtType(currClass.getName());
	}
	public IType getJdtType(String currClass) {
		IType type = null;
		if(project_ != null){
			IJavaProject javaProj = JavaCore.create(project_);
			if(javaProj != null){
				try {
					type = javaProj.findType(currClass);
					if(type != null){
						type.getOpenable().open(null);
					}
				} catch (Exception e) {
					EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
				}
			}
		}
		return type;
	}
	
	private String readIntoString(Reader docContent) throws IOException {
		StringBuffer buf = new StringBuffer();
		int BUF_SIZE = 100;
		char[] temp = new char[BUF_SIZE];
		int read = 0;
		while( (read = docContent.read(temp)) > 0){
			buf.append(temp, 0, read);
		}
		return buf.toString();
	}
	
	public String addMethodCompletionForClass(int offset, List retValueList, String prefix, String typeDescriptor, String filter) {
		try {
			if(typeDescriptor != null){
				IType type = getJdtType(typeDescriptor);
				
				if(type != null){
					IMethod[] methods;
					methods = type.getMethods();
					
					for (int j = 0; j < methods.length; j++) {
						IMethod currMethod = methods[j];
						String name = currMethod.getElementName();
						// filter out the method not starting with the filter string
						if(!name.startsWith(filter)){
							continue;
						}
						StringBuffer paramList = new StringBuffer("(");
						
						String[] argumentsTypes = currMethod.getParameterTypes();
						if(argumentsTypes.length > 0 ){
							for (int k = 0; k < argumentsTypes.length; k++) {
								paramList.append(argumentsTypes[k]);
								paramList.append(',');
							}
							paramList.deleteCharAt(paramList.length()-1);
						}
						paramList.append(')');
						String javadoc = getJavaDoc(currMethod);
						if(javadoc == null){
							javadoc = "Method - No Javadoc available";
						}
						retValueList.add(new CompletionProposal(name, offset-filter.length(), filter.length(), name.length(), null, currMethod.getElementName()+paramList.toString()+ " - " + typeDescriptor, null, javadoc));
//						TODO: use  JavadocContentAccess  to ge the JavaDoc for the IMember 
//						JavaCore.getJavaCore().getJavaCore()
					}
				} else {
					try {
						if(typeDescriptor.length() > 0) {
							Class reflectionType = Class.forName(typeDescriptor);
							Method[] methods = reflectionType.getMethods();
							for (int i = 0; i < methods.length; i++) {
								Method currMethod = methods[i];
								String name = currMethod.getName();
								int lastFullstop = name.lastIndexOf('.');
								String nonQualifiedName = name.substring(lastFullstop+1);
								if(!name.startsWith(filter)){
									continue;
								}
								// format param list
								Class[] paramTypes = currMethod.getParameterTypes();
								StringBuffer paramList = new StringBuffer("(");
								if(paramTypes != null && paramTypes.length>0){
									if(paramTypes.length > 0 ){
										for (int k = 0; k < paramTypes.length; k++) {
											paramList.append(paramTypes[k]);
											paramList.append(',');
										}
										paramList.deleteCharAt(paramList.length()-1);
									}
									
								}
								paramList.append(')');
								
								// add proposal 
								String fullDescription = nonQualifiedName+paramList.toString()+ " : " +currMethod.getReturnType().getName();
								retValueList.add(new CompletionProposal(nonQualifiedName, offset-filter.length(), filter.length(), nonQualifiedName.length(), null,  fullDescription , null, fullDescription));
							}
						}
					} catch (ClassNotFoundException e) {
						EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
					}
					
				}
			} 
		} catch (JavaModelException e) {
			EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
		}
		return prefix;
	}
	
	
}
